<?php

namespace app\api\service\weixin;

use app\common\BaseHelper;
use app\lib\exception\PayException;
use app\api\controller\Base;

use think\Exception;
use think\Loader;
use think\Log;

Loader::import('WxPay.WxPay',EXTEND_PATH,'.Api.php');

/**
 * 微信支付类，要实现支付需要继承此类
 * 生成微信预订单、统一下单、签名算法、返回小程序需要的支付参数
 * Class BasePay
 * @package app\api\service\weixin
 */
class BasePay extends Base
{

    /**
     * 支付入口方法
     * @param $totalPrice 订单金额
     * @param $productName 商品名称
     * @param $openid 小程序用户openid
     * @param $orderID 订单号
     * @param $pay_back_url 支付回调地址
     * @return array
     */
    public function run($totalPrice,$productName,$openid,$orderID,$pay_back_url){
        return $this->makeWxPreOrder($totalPrice,$productName,$openid,$orderID,$pay_back_url);
    }

    /**
     * 生成微信预订单
     * @param $totalPrice
     * @return array
     */
    private function makeWxPreOrder($totalPrice,$productName,$openid,$orderID,$pay_back_url){
        $wxOrderData = new \WxPayUnifiedOrder();
        $wxOrderData->SetOut_trade_no($orderID);
        $wxOrderData->SetTrade_type('JSAPI');
        $wxOrderData->SetTotal_fee($totalPrice);
        $wxOrderData->SetBody($productName);
        $wxOrderData->SetOpenid($openid);
        $wxOrderData->SetNotify_url($pay_back_url);
        return $this->getPaySignature($wxOrderData);

    }
    /**
     * 请求微信统一下单接口返回给客户端一组支付参数
     */
    private function getPaySignature($wxOrderData){
        $wxOrder = \WxPayApi::unifiedOrder($wxOrderData);
        if($wxOrder['return_code'] != 'SUCCESS' || $wxOrder['result_code'] != 'SUCCESS'){
            Log::record($wxOrder,'error');
            Log::record('获取预支付订单失败','error');
        }
        if($wxOrder['return_code'] == 'FAIL'){
            throw new PayException([
                'msg' => $wxOrder['return_msg']
            ]);
        }
        $this->recordPreOrder($wxOrder);

        return $this->sign($wxOrder);
    }

    protected function recordPreOrder($wxOrder){
        //存储预支付交易会话标识 子类需要覆盖

    }

    /**
     * 生成签名
     */
    private function sign($wxOrder){
        $jsApiPayData = new \WxPayJsApiPay();
        $jsApiPayData->SetAppid(config('wx.app_id'));
        $jsApiPayData->SetTimeStamp((string)time());
        $jsApiPayData->SetNonceStr(BaseHelper::getUUID());
        $jsApiPayData->SetPackage('prepay_id='.$wxOrder['prepay_id']);
        $jsApiPayData->SetSignType('md5');
        $sign = $jsApiPayData->MakeSign();
        $rowValues = $jsApiPayData->GetValues();
        $rowValues['paySign'] = $sign;
        unset($rowValues['appId']);
        return $rowValues;
    }
}